package com.apestech.api.workflow;

import com.apestech.api.workflow.extend.FlowDatabase;
import com.apestech.api.workflow.lib.FlowUtil;
import com.apestech.api.workflow.lib.app.*;
import com.apestech.api.workflow.lib.element.FlowExecute;
import com.apestech.api.workflow.lib.element.FlowQuery;
import com.apestech.api.workflow.lib.element.WorkProcessEngine;
import com.apestech.framework.json.JSONArray;
import com.apestech.framework.json.JSONObject;
import org.flowable.engine.ManagementService;
import org.flowable.engine.ProcessEngine;
import org.flowable.task.api.Task;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;

/**
 * OA API中不需要SESSION部分函数合集
 *
 * @author hup
 * @create 2018-07-23-17:07
 */
public class WorkFlow extends FlowUtil {

    private WorkProcessEngine engine;

    public WorkFlow(ProcessEngine engine) throws Exception {
        this.engine=new WorkProcessEngine(engine);
    }

    public WorkProcessEngine getEngine() {
        return engine;
    }

    /**
     * OA文件按目录部署
     * @param dir
     * @throws Exception
     */
    public void refreshDeployment(String dir) throws Exception {
        FlowOtherApp other=new FlowOtherApp(engine);
        other.refreshDeployment(dir);
    }

    /**
     * 初始化OA扩展相关表结构
     * @throws Exception
     */
    public void iniDataBase() throws Exception {
        FlowDatabase db=new FlowDatabase(engine);
        db.iniDataBase();
    }

    /**
     * 查询结点路由信息
     * @param taskId
     * @return
     * @throws Exception
     */
    public JSONArray getDecision(String taskId) throws Exception {
        JSONObject input=new JSONObject();
        input.put("taskId", taskId);
        TaskQueryApp qapp=new TaskQueryApp(engine, input);
        return qapp.getDecision();
    }

    /**
     * 查询结点路由信息
     * @param processInstanceId
     * @return
     * @throws Exception
     */
    public JSONArray getDecisionByProcessInstanceId(String processInstanceId) throws Exception {
        JSONObject input=new JSONObject();
        input.put("processInstanceId", processInstanceId);
        TaskQueryApp qapp=new TaskQueryApp(engine, input);
        return qapp.getDecision();
    }

    /**
     * 查询人员待办
     * @param userId
     * @return
     * @throws Exception
     */
    public JSONArray getUserToDoTask(String userId) throws Exception {
        FlowOtherApp other=new FlowOtherApp(engine);
        return other.getUserToDoTask(userId);
    }

    /**
     * 根据taskId或processInstanceId获取指定结点或某个进程运行时结点下的候选人列表
     * @param input taskId或processInstanceId
     * @return
     * @throws Exception
     */
    public ArrayList<String> getTaskUserList(JSONObject input) throws Exception {
        FlowOtherApp other=new FlowOtherApp(engine);
        return other.getTaskUserList(input);
    }

    /**
     * 根据taskId或processInstanceId获取指定结点或某个进程运行时结点下的变量信息
     * @param input taskId或processInstanceId
     * @return
     * @throws Exception
     */
    public JSONObject getTaskMap(JSONObject input) throws Exception {
        FlowOtherApp other=new FlowOtherApp(engine);
        return other.getTaskMap(input);
    }

    /**
     * 查询当前单据OA结点状态
     * @param input 必填字段：processInstanceId 或 taskId
     * @return
     * @throws Exception
     */
    public String getNodeState(JSONObject input) throws Exception {
        TaskQueryApp qapp=new TaskQueryApp(engine, input);
        return qapp.getNodeState();
    }

    /*---------------------WorkflowDB----------------------*/
    /**
     * 开启流程
     * @param input 必填字段：processDefinitionKey、businessKey
     * @return processInstanceId OA流程ID
     * @throws Exception
     */
    public String startProcess(JSONObject input) throws Exception {
        FlowApp app=new FlowApp(engine, input);
        return app.startProcess();
    }

    /**
     * 给结点赋用户；
     * 选填字段：processInstanceId
     * @param input 必填字段：taskId，userlist [ArrayList<String>]
     * @throws Exception
     */
    public void assignTaskToUser(JSONObject input) throws Exception {
        FlowApp app=new FlowApp(engine, input);
        app.assignTaskToUser();
    }

    /**
     * 给结点赋用户；
     * @param taskId
     * @param userId
     * @throws Exception
     */
    public void assignTaskToUser(String taskId, String userId) throws Exception {
        FlowExecute exec=new FlowExecute(engine);
        exec.assignTaskToUser(taskId, userId);
    }

    /**
     * 用户签收
     * @param input 必填字段：（taskId 或 processInstanceId），userId
     * @throws Exception
     */
    public void claimUser(JSONObject input) throws Exception {
        FlowApp app=new FlowApp(engine, input);
        app.claimUser();
    }

    /**
     * 任务执行
     * @param input 必填字段：（taskId 或 processInstanceId）
     * @throws Exception
     */
    public void processTask(JSONObject input) throws Exception {
        FlowApp app=new FlowApp(engine, input);
        app.processTask();
    }

    /**
     * 任务中止
     * @param input 必填字段：（taskId 或 processInstanceId），opinion
     * @throws Exception
     */
    public Task stopProcess(JSONObject input) throws Exception {
        FlowApp app=new FlowApp(engine, input);
        return app.stopProcess();
    }

    /**
     * 改签
     * 选填字段：opinion，result，businessKey
     * @param input 必填字段：（taskId 或 processInstanceId），userId，userName，loginUserId，loginUserName
     * @throws Exception
     */
    public void changeSignTask(JSONObject input) throws Exception {
        ChangeSignApp app=new ChangeSignApp(engine, input);
        app.changeSignTask();
    }

    /**
     * 会签发起
     * userlist为JSONArray类型，每个MAP包括userId，userName
     * 选填字段：opinion，result，businessKey
     * @param input 必填字段：userlist，（taskId 或 processInstanceId），loginUserId，loginUserName
     * @throws Exception
     */
    public JSONObject startCounterSign(JSONObject input) throws Exception {
        CounterSignApp app=new CounterSignApp(engine, input);
        app.startCounterSign();
        return app.getInput();
    }

    /**
     * 会签回应
     * 选填字段：opinion，result，businessKey
     * @param input 必填字段：（taskId 或 processInstanceId），loginUserId，loginUserName
     * @throws Exception
     */
    public void execCounterSign(JSONObject input) throws Exception {
        CounterSignApp app=new CounterSignApp(engine, input);
        app.execCounterSign();
    }

    /**
     * 加签发起
     * 选填字段：opinion，result，businessKey
     * @param input 必填字段：（taskId 或 processInstanceId），userId，userName，loginUserId，loginUserName
     * @throws Exception
     */
    public void startAddSign(JSONObject input) throws Exception {
        AddSignApp app=new AddSignApp(engine, input);
        app.startAddSign();
    }

    /**
     * 加签
     * 选填字段：opinion，result，businessKey
     * @param input 必填字段：（taskId 或 processInstanceId），userId，userName，loginUserId，loginUserName
     * @throws Exception
     */
    public void addSign(JSONObject input) throws Exception {
        AddSignApp app=new AddSignApp(engine, input);
        app.addSign();
    }

    /**
     * 加签执行
     * 选填字段：opinion，result，businessKey
     * @param input 必填字段：（taskId 或 processInstanceId），loginUserId，loginUserName
     * @throws Exception
     */
    public void execAddSign(JSONObject input) throws Exception {
        AddSignApp app=new AddSignApp(engine, input);
        app.execAddSign();
    }

    /**
     * 加签转签
     * 选填字段：opinion，result，businessKey
     * @param input 必填字段：（taskId 或 processInstanceId），userId，userName，loginUserId，loginUserName
     * @throws Exception
     */
    public void changeAddSign(JSONObject input) throws Exception {
        AddSignApp app=new AddSignApp(engine, input);
        app.changeSign();
    }

    /**
     * 获取流程图
     * @param input 必填字段processInstanceId
     * @return
     * @throws Exception
     */
    public InputStream getProcessInstancePng(JSONObject input)throws Exception{
        FlowApp app=new FlowApp(engine, input);
        return app.getProcessInstancePng();
    }

    /**
     * 驱回
     * @param input 必填字段taskId(当前正在执行的任务ID), loginUserId, loginUserName
     * @throws Exception
     */
    public void refoulement(JSONObject input)throws Exception{
        FlowJumpApp app=new FlowJumpApp(engine,input,true);
        ManagementService managementService = engine.getManagementService();
        managementService.executeCommand(app);
        if(app.getError()!=null){
            throw new Exception(app.getError());
        }
    }

    /**
     * 撤消
     * @param input 必填字段taskId（整个流程并没完成下已经完成的任务ID）,loginUserId, loginUserName
     * @throws Exception
     */
    public void rollBack(JSONObject input)throws Exception{
        FlowJumpApp app=new FlowJumpApp(engine,input,false);
        ManagementService managementService = engine.getManagementService();
        managementService.executeCommand(app);
        if(app.getError()!=null){
            throw new Exception(app.getError());
        }
    }

    /**
     * 获取任务更新时间
     * @param taskId
     * @return
     * @throws Exception
     */
    public Date getTaskUpdateTime(String taskId) throws Exception {
        FlowQuery query=new FlowQuery(engine);
        return query.getTaskUpdateTime(taskId);
    }

    /**
     * 获取任务的时间，如存在扩展结点，获取扩展结点的最后更新时间，如无，取任务的创建时间
     * @param task
     * @param userId
     * @return
     * @throws Exception
     */
    public Date getTaskUpdateTime(Task task, String userId) throws Exception {
        FlowQuery query=new FlowQuery(engine);
        return query.getPersonTaskTime(task, userId);
    }

    /**
     * 开始委托
     * @param input 必填：loginUserId，loginUserName登录人， userId，userName委托人；
     *              非必填：startDate开始时间字串类型，endDate结束时间字串类型，opinion意见
     * @throws Exception
     */
    public void startCommission(JSONObject input) throws Exception {
        FlowDatabase db=new FlowDatabase(engine);
        db.startCommission(input);
    }

    /**
     * 中止委托
     * @param userId 当前登录人员
     * @throws Exception
     */
    public void stopCommission(String userId) throws Exception {
        FlowDatabase db=new FlowDatabase(engine);
        db.stopCommission(userId);
    }

    /**
     * 获取当前用户委托人
     * @param userId 当前登录人员
     * @return
     * @throws Exception
     */
    public String getCommission(String userId) throws Exception {
        return getCommission(engine, userId);
    }

    /**
     * 查询任务结点列表
     * @param param
     * @return
     * @throws Exception
     */
    public JSONArray getTaskList(JSONObject param) throws Exception {
        FlowQuery query=new FlowQuery(engine);
        return query.getTaskList(param);
    }

    public JSONObject getTaskList(JSONObject param, int size, int page) throws Exception {
        FlowQuery query=new FlowQuery(engine);
        return query.getTaskList(param, size, page);
    }

    /**
     * 查询流程列表
     * @param param
     * @return
     * @throws Exception
     */
    public JSONArray getProcList(JSONObject param) throws Exception {
        FlowQuery query=new FlowQuery(engine);
        return query.getProcList(param);
    }

    public JSONObject getProcList(JSONObject param, int size, int page) throws Exception {
        FlowQuery query=new FlowQuery(engine);
        return query.getProcList(param, size, page);
    }

}
